package org.apache.shiro.listener;

import java.beans.PropertyVetoException;
import java.io.Serializable;
import java.util.Deque;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liwbn.rbac.common.conf.Constants;
import sun.org.mozilla.javascript.internal.ast.CatchClause;

/**
 * 监听shiro session
 * Created by liwb on 2016-8-4.
 */
public class RbacSessionListener implements SessionListener {

    private static final Logger LOGGER = LoggerFactory
            .getLogger(RbacSessionListener.class);

    private static final String DEFAULT_CACHE_NAME = "rbac-session-online";
    // 在线用户缓存
    private String cacheName;
    //
    private EhCacheManager ehCacheManager;

    // 储存登陆用户信息
    private Cache<Object, Deque<Serializable>> cache;

    private RbacSessionListener() {
    }

    public RbacSessionListener(EhCacheManager ehCacheManager) {
        this.ehCacheManager = ehCacheManager;
        this.cacheName = DEFAULT_CACHE_NAME;
        this.cache = ehCacheManager.getCache(cacheName);
        LOGGER.info("获取cache缓存[{}]", cacheName);
    }

    public RbacSessionListener(EhCacheManager ehCacheManager,
            String cacheName) {
        this.ehCacheManager = ehCacheManager;
        this.cacheName = cacheName;
        this.cache = ehCacheManager.getCache(cacheName);
        LOGGER.info("获取cache缓存[{}]", cacheName);
    }

    @Override
    public void onStart(Session session) {
        Serializable sessionId = session.getId();
        LOGGER.info("session已启动 {}", sessionId);
    }

    /**
     * session停止后需要将该sessionId从缓存的Deque中删除
     * 
     * @param session
     */
    @Override
    public void onStop(Session session) {
        Serializable sessionId = session.getId();
        Object currentUser = session.getAttribute(Constants.CURRENT_USER);
        LOGGER.info("session停止 {}", sessionId);
        removeCache(sessionId, currentUser);
    }

    @Override
    public void onExpiration(Session session) {
        Serializable sessionId = session.getId();
        Object currentUser = session.getAttribute(Constants.CURRENT_USER);
        LOGGER.info("session过期 {}", sessionId);
        removeCache(sessionId, currentUser);
    }

    private void removeCache(Serializable sessionId, Object currentUser) {
        if (currentUser != null) {
            // 只有登陆的用户需要该处理
            Deque<Serializable> deque = cache.get(currentUser);
            // 队列为空,则清除缓存
            if (deque == null || deque.size() < 1) {
                try {
                    cache.remove(currentUser);
                } catch (CacheException e) {
                    LOGGER.error(e.getMessage());
                }
            } else
            // 单用户过期时清除该缓存
            if (deque.size() == 1 && deque.contains(sessionId)) {
                try {
                    cache.remove(currentUser);
                } catch (CacheException e) {
                    LOGGER.error(e.getMessage());
                }
            } else
            // 多用户时清掉该sessionId
            if (deque.contains(sessionId)) {
                deque.remove(sessionId);
            }
            LOGGER.info("Deque info: {}", deque.toArray());
        }
    }
}
